#pragma once
#include <functional>
#include <tuple>
// 普通函数.
// 函数指针.
// function/lambda.
// 成员函数.
// 函数对象.

// 这是一个函数特征萃取模板，用于提取各种类型函数的特征
// 支持以下几种函数类型：
// 1. 普通函数
// 2. 函数指针
// 3. std::function/lambda
// 4. 成员函数
// 5. 函数对象(仿函数)

// 转换为std::function和函数指针.
template <typename T>
struct function_traits;

// 普通函数.
template <typename Ret, typename... Args>
struct function_traits<Ret(Args...)>
{
public:
	enum
	{
		arity = sizeof...(Args)
	};														// 获取函数参数个数
	typedef Ret function_type(Args...);	//定义了一个function_type 用就是通过这个用的					// 函数类型
	typedef Ret return_type;								// 返回值类型
	using stl_function_type = std::function<function_type>; // 对应的std::function类型
	typedef Ret (*pointer)(Args...);						// 函数指针类型

	// 获取第I个参数的类型
	template <size_t I>
	struct args
	{
		static_assert(I < arity, "index is out of range, index must less than sizeof Args");
		using type = typename std::tuple_element<I, std::tuple<Args...>>::type;
	};

	// 参数类型列表，移除cv限定符和引用
	typedef std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...> tuple_type;
	typedef std::tuple<std::remove_const_t<std::remove_reference_t<Args>>...> bare_tuple_type;
};

// 函数指针.
template <typename Ret, typename... Args>
struct function_traits<Ret (*)(Args...)> : function_traits<Ret(Args...)>
{
};

// std::function.
template <typename Ret, typename... Args>
struct function_traits<std::function<Ret(Args...)>> : function_traits<Ret(Args...)>
{
};

// member function.
// 使用宏来处理成员函数的四种cv限定符情况
#define FUNCTION_TRAITS(...)                                                                                      \
	template <typename ReturnType, typename ClassType, typename... Args>                                          \
	struct function_traits<ReturnType (ClassType::*)(Args...) __VA_ARGS__> : function_traits<ReturnType(Args...)> \
	{                                                                                                             \
	};

FUNCTION_TRAITS()				// 普通成员函数
FUNCTION_TRAITS(const)			// const成员函数
FUNCTION_TRAITS(volatile)		// volatile成员函数
FUNCTION_TRAITS(const volatile) // const volatile成员函数

// 函数对象.
template <typename Callable>
struct function_traits : function_traits<decltype(&Callable::operator())>
{
};

// 转换辅助函数：将lambda表达式转换为std::function
template <typename Function>
typename function_traits<Function>::stl_function_type to_function(const Function &lambda)
{
	return static_cast<typename function_traits<Function>::stl_function_type>(lambda);
}

template <typename Function>
typename function_traits<Function>::stl_function_type to_function(Function &&lambda)
{
	return static_cast<typename function_traits<Function>::stl_function_type>(std::forward<Function>(lambda));
}

// 转换辅助函数：将lambda表达式转换为函数指针
template <typename Function>
typename function_traits<Function>::pointer to_function_pointer(const Function &lambda)
{
	return static_cast<typename function_traits<Function>::pointer>(lambda);
}
